<?php
namespace app\service;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use plugin\saiadmin\exception\ApiException;

class JwtService
{
    /**
     * 密钥
     * @var string
     */
    private static $key = 'www_gzj2001_com';

    /**
     * 算法
     * @var string
     */
    private static $alg = 'HS256';

    /**
     * token过期时间（秒）
     * @var int
     */
    private static $exp = 720000; // 2小时

    /**
     * 生成token
     * @param array $userData
     * @return string
     */
    public static function generateToken(array $userData): string
    {
        $time = time();
        $payload = [
            'iss' => 'ai_project', // 签发者
            'aud' => 'mini_program', // 接收者
            'iat' => $time, // 签发时间
            'nbf' => $time, // 生效时间
            'exp' => $time + self::$exp, // 过期时间
            'data' => [ // 自定义数据
                'user_id' => $userData['id'],
                'openid' => $userData['openid'],
                'nickname' => $userData['nickname'],
                'level' => $userData['level'],
                'status' => $userData['status']
            ]
        ];

        return JWT::encode($payload, self::$key, self::$alg);
    }

    /**
     * 验证token
     * @param string $token
     * @return array
     * @throws ApiException
     */
    public static function validateToken(string $token): array
    {
        try {
            if (empty($token)) {
                throw new ApiException('token不能为空', 401);
            }

            $decoded = JWT::decode($token, new Key(self::$key, self::$alg));
            return (array)$decoded->data;
        } catch (\Exception $e) {
            throw new ApiException('token无效或已过期', 401);
        }
    }

    /**
     * 刷新token
     * @param string $token
     * @return string
     * @throws ApiException
     */
    public static function refreshToken(string $token): string
    {
        $userData = self::validateToken($token);
        return self::generateToken($userData);
    }

    /**
     * 从请求头获取token
     * @return string
     */
    public static function getRequestToken(): string
    {
        return request()->header('token', '');
    }
}
